<template>
  <div
    :style="{ width: (props.width) + 'px', height: ( props.height) + 'px', background: (props.bgColor) || 'none' }"
  >
    <div id="player"></div>
  </div>
</template>

<script setup lang="ts">
import { ref, watch } from 'vue'
import { ComponentInstance } from '@/types/visual-app'
import cloudRenderer from "uesuperapi";
const props = defineProps<ComponentInstance>()
import { useDynamicComponentStore } from '@/store/dynamicComponent'
import { onBeforeUnmount } from 'vue-demi';
import { onMounted } from 'vue-demi';
import { computed } from 'vue-demi';
import { transformData} from '@/utils/visual/ConfigUtil'
import Controls from 'xgplayer/es/plugins/controls';
const dynamicComponentStore = useDynamicComponentStore()
const emit = defineEmits<{
  (e: 'connection-info', payload: { code: number, msg: string }): void
  (e: 'register-cloud-response', payload: any): void
  (e: 'connection-completed', payload: any): void
  
}>()

// 本地变量响应 props.config
const localAppId = ref(props.config?.appId || '')
const localCloudUrl = ref(props.config?.cloudUrl || '')
const localAuthorization = ref(props.config?.authorization || '')
const localAutoplay= ref(props.config?.autoplay || false)
const localTimeout = ref(props.config?.timeout || 120)
const localBindings = ref<any[]>(Array.isArray(props.bindings) ? [...props.bindings] : [])

const isStreamConnected = ref(false);
(window as any).cloudRender = undefined;


// 启动渲染流
const openVideoStreaming = async () => {
  // emit 之前先调用所有绑定的 connection-info 方法
  await triggerEventMethods('connection-info', {
    code: 0,
    msg: '正在请求启动渲染场景...'
  });
  
  emit('connection-info', {
    code: 0,
    msg: '正在请求启动渲染场景...'
  });
  Promise.race([
    fetch(`${localCloudUrl.value}`, {
      method: "POST",
      headers: new Headers({
        "Content-type": "application/json",
        "Authorization": localAuthorization.value || ''
      }),
      body: JSON.stringify({ appid: localAppId.value, resX: props.width, resY: props.height })
    }),
    new Promise(function (_resolve: any, reject) {
      setTimeout(() => reject(new Error('请求超时，请检查网络或服务端')), 1000 * localTimeout.value)
    })])
    .then(async (res: any) => {
      if (!res.ok) {
        await triggerEventMethods('connection-info', {
          code: -5,
          msg: `服务端响应异常：${res.statusText}`
        });
        emit('connection-info', {
          code: -5,
          msg: `服务端响应异常：${res.statusText}`
        });
		
		await triggerEventMethods('connection-completed', {
		  code: -5,
		  msg: `服务端响应异常：${res.statusText}`
		});
		
		emit('connection-completed', {
		  code: -5,
		  msg: `服务端响应异常：${res.statusText}`
		});
        throw Error(res.statusText)
      }
      return res.json()
    }).then(async res => {
      if (res.code != 200) {
        await triggerEventMethods('connection-info', {
          code: res.code,
          msg: `服务端返回错误：${res.msg}`
        });
        emit('connection-info', {
          code: res.code,
          msg: `服务端返回错误：${res.msg}`
        });
		
		await triggerEventMethods('connection-completed', {
          code: res.code,
          msg: `服务端返回错误：${res.msg}`
		});
		
		emit('connection-completed', {
          code: res.code,
          msg: `服务端返回错误：${res.msg}`
		});
        throw Error(res.msg)
      }
      return res.data
    }).then(async (data: any) => {
      (window as any).cloudRender = new cloudRenderer("player", 0);

      await triggerEventMethods('connection-info', {
        code: 1,
        msg: '数字世界正在开启中...'
      });
      emit('connection-info', {
        code: 1,
        msg: '数字世界正在开启中...'
      });

      SuperAPI("OnStreamConnected", async () => {
        isStreamConnected.value = true;
        await triggerEventMethods('connection-info', {
          code: 2,
          msg: '数字世界已开启'
        });
        emit('connection-info', {
          code: 2,
          msg: '数字世界已开启'
        });
      });
	  
	  await triggerEventMethods('connection-completed', {
          code: 2,
          msg: '数字世界已开启'
	  });
	  
	  emit('connection-completed', {
          code: 2,
          msg: '数字世界已开启'
	  });
	  
	  

      SuperAPI("OnStreamClosed", async () => {
        isStreamConnected.value = false;
        await triggerEventMethods('connection-info', {
          code: -1,
          msg: '数字世界已关闭'
        });
        emit('connection-info', {
          code: -1,
          msg: '数字世界已关闭'
        });
		
		
		await triggerEventMethods('connection-completed', {
          code: -1,
          msg: '数字世界已关闭'
		});
		
		emit('connection-completed', {
          code: -1,
          msg: '数字世界已关闭'
		});
		
      });

      SuperAPI("RegisterCloudResponse", function (e: any) {
        triggerEventMethods('register-cloud-response', e);
        emit('register-cloud-response', e);
      });

      SuperAPI("StartRenderCloud", getProxySocketUrl(data.url));
    })
    .catch(async (err) => {
		
		console.log(err)
		
      await triggerEventMethods('connection-info', {
        code: -99,
        msg: err.message || '请求异常'
      });
      emit('connection-info', {
        code: -99,
        msg: err.message || '请求异常'
      });
	  
	  await triggerEventMethods('connection-completed', {
        code: -99,
        msg: err.message || '请求异常'
	  });
	  
	  emit('connection-completed', {
        code: -99,
        msg: err.message || '请求异常'
	  });
    });
}

const SuperAPI = (method: string, jsonData: any) => {
  if ((window as any).cloudRender) {
    (window as any).cloudRender.SuperAPI(method, jsonData);
  }
}

const closeVideoStreaming = () => {
  try {
    SuperAPI("StopRenderCloud", {});
  } catch (e) {
  }
  isStreamConnected.value = false;
  (window as any).cloudRender = undefined;
}

const startPickLocation = () => {
  var jsondata = {
    icon: false,
    info: false,
  }
  SuperAPI("StartPickLocation", jsondata);
}

const endPickLocation = () => {
    SuperAPI("EndPickLocation", {});
}

const getProxySocketUrl=(url:any)=> {
	const browserUrl = new URL(window.location.href);
	if('https:'===browserUrl.protocol){
		return  "wss://"+browserUrl.hostname+"/"+url.replace("ws://","");
	}else{
		return url;
	}
}

const triggerEventMethods=async (eventType: string, ...args: any[]) =>{
  const eventBindings = localBindings.value.filter(
    b => b.event === eventType && b.target && b.targetMethod
  )
  for (const binding of eventBindings) {
    const instance = dynamicComponentStore.getRef(binding.target)
    if (instance && typeof instance.ref[binding.targetMethod] === 'function') {
	  if(binding.params){
		  let param=transformData(binding.params,args[0])
		  instance.ref[binding.targetMethod](param)
	  }
	  else{
		  instance.ref[binding.targetMethod](...args)
	  }
    }
  }
}

defineExpose({
  openVideoStreaming,
  closeVideoStreaming,
  SuperAPI,
  startPickLocation,
  endPickLocation,
  isStreamConnected
});


const connectionInfoElements = computed(() =>
  localBindings.value
    .filter(b => b.type === "connection-info")
    .map(b => dynamicComponentStore.getRef(b.target))
    .filter(Boolean) // 过滤掉未找到的
)

// 监听配置变化
watch(() => props.config?.appId, val => {
  localAppId.value = val || ''
})

watch(() => props.config?.cloudUrl, val => {
  localCloudUrl.value = val || ''
})

watch(() => props.config?.authorization, val => {
  localAuthorization.value = val || ''
})

watch(() => props.config?.autoplay, val => {
  localAutoplay.value = val === true
})

watch(() => props.config?.timeout, val => {
  localTimeout.value = val || 60
})

watch(() => props.config?.bindings, val => {
  localAutoplay.value = val === true
})

watch(() => props?.bindings, (val) => {
  if (Array.isArray(val)) {
    localBindings.value = [...val]
  } else {
    localBindings.value = []
  }
})

onBeforeUnmount(() => {
  try {
    SuperAPI("StopRenderCloud", {});
  } catch (e) {
  }
  isStreamConnected.value = false;
  (window as any).cloudRender = undefined;
})

onMounted(() => {
  if (localAutoplay.value === true) {
	openVideoStreaming()
  }
})

</script>

<style scoped>
#player {
  width: 100%;
  height: 100%;
}
</style>
  